/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _H_LIBZLANG_STDIO_
#define _H_LIBZLANG_STDIO_

#include "zlang.h"

struct ZlangObject_stdin;
struct ZlangObject_stdout;
struct ZlangObject_stderr;
struct ZlangObject_stdfile;
struct ZlangObject_execmd;

#define ZLANG_OBJECT_stdin	"stdin"
#define ZLANG_OBJECT_stdout	"stdout"
#define ZLANG_OBJECT_stderr	"stderr"
#define ZLANG_OBJECT_stdfile	"stdfile"
#define ZLANG_OBJECT_execmd	"execmd"

#define EXCEPTION_MESSAGE_OPEN_FILE_FAILED	"open file failed"
#define EXCEPTION_MESSAGE_STAT_FILE_FAILED	"stat file failed"
#define EXCEPTION_MESSAGE_WRITE_FILE_FAILED	"write file failed"
#define EXCEPTION_MESSAGE_DPOPEN_FAILED		"dpopen failed"
#define EXCEPTION_MESSAGE_DPHALFCLOSE_FAILED	"dphalfclose failed"
#define EXCEPTION_MESSAGE_DPCLOSE_FAILED	"dpclose failed"

DLLEXPORT ZlangImportObjectsFunction ZlangImportObjects;
int ZlangImportObjects( struct ZlangRuntime *rt );

#define FSCANF_STRING_AND_SET_LENGTH_OUTPUT(_in_) \
	struct ZlangObject	*in1 = GetInputParameterInLocalObjectStack(rt,1) ; \
	struct ZlangObject	*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	int32_t			data_len ; \
	\
	fscanf( _in_ , "%4095s" , _g_zlang_string_buffer ); \
	data_len = (int32_t)strlen(_g_zlang_string_buffer) ; \
	FromCharPtr( rt , in1 , _g_zlang_string_buffer , data_len ); \
	CallRuntimeFunction_int_SetIntValue( rt , out1 , data_len ); \

#define FSCANF_SHORT_AND_SET_LENGTH_OUTPUT(_in_) \
	struct ZlangObject	*in1 = GetInputParameterInLocalObjectStack(rt,1) ; \
	struct ZlangObject	*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	int16_t			s ; \
	int32_t			data_len ; \
	\
	data_len = fscanf( _in_ , "%"SCNi16"" , & s ) ; \
	CallRuntimeFunction_short_SetShortValue( rt , in1 , s ); \
	CallRuntimeFunction_int_SetIntValue( rt , out1 , data_len ); \

#define FSCANF_USHORT_AND_SET_LENGTH_OUTPUT(_in_) \
	struct ZlangObject	*in1 = GetInputParameterInLocalObjectStack(rt,1) ; \
	struct ZlangObject	*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	uint16_t		us ; \
	int32_t			data_len ; \
	\
	data_len = fscanf( _in_ , "%"SCNu16"" , & us ) ; \
	CallRuntimeFunction_ushort_SetUShortValue( rt , in1 , us ); \
	CallRuntimeFunction_int_SetIntValue( rt , out1 , data_len ); \

#define FSCANF_INT_AND_SET_LENGTH_OUTPUT(_in_) \
	struct ZlangObject	*in1 = GetInputParameterInLocalObjectStack(rt,1) ; \
	struct ZlangObject	*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	int32_t			i ; \
	int32_t			data_len ; \
	\
	data_len = fscanf( _in_ , "%"SCNi32"" , & i ) ; \
	CallRuntimeFunction_int_SetIntValue( rt , in1 , i ); \
	CallRuntimeFunction_int_SetIntValue( rt , out1 , data_len ); \

#define FSCANF_UINT_AND_SET_LENGTH_OUTPUT(_in_) \
	struct ZlangObject	*in1 = GetInputParameterInLocalObjectStack(rt,1) ; \
	struct ZlangObject	*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	uint32_t		ui ; \
	int32_t			data_len ; \
	\
	data_len = fscanf( _in_ , "%"SCNu32"" , & ui ) ; \
	CallRuntimeFunction_uint_SetUIntValue( rt , in1 , ui ); \
	CallRuntimeFunction_int_SetIntValue( rt , out1 , data_len ); \

#define FSCANF_LONG_AND_SET_LENGTH_OUTPUT(_in_) \
	struct ZlangObject	*in1 = GetInputParameterInLocalObjectStack(rt,1) ; \
	struct ZlangObject	*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	int64_t			l ; \
	int32_t			data_len ; \
	\
	data_len = fscanf( _in_ , "%"SCNi64"" , & l ) ; \
	CallRuntimeFunction_long_SetLongValue( rt , in1 , l ); \
	CallRuntimeFunction_int_SetIntValue( rt , out1 , data_len ); \

#define FSCANF_ULONG_AND_SET_LENGTH_OUTPUT(_in_) \
	struct ZlangObject	*in1 = GetInputParameterInLocalObjectStack(rt,1) ; \
	struct ZlangObject	*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	uint64_t		ul ; \
	int32_t			data_len ; \
	\
	data_len = fscanf( _in_ , "%"SCNu64"" , & ul ) ; \
	CallRuntimeFunction_ulong_SetULongValue( rt , in1 , ul ); \
	CallRuntimeFunction_int_SetIntValue( rt , out1 , data_len ); \

#define FSCANF_FLOAT_AND_SET_LENGTH_OUTPUT(_in_) \
	struct ZlangObject	*in1 = GetInputParameterInLocalObjectStack(rt,1) ; \
	struct ZlangObject	*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	float			f ; \
	int			data_len ; \
	\
	data_len = fscanf( _in_ , "%f" , & f ) ; \
	CallRuntimeFunction_float_SetFloatValue( rt , in1 , f ); \
	CallRuntimeFunction_int_SetIntValue( rt , out1 , data_len ); \

#define FSCANF_DOUBLE_AND_SET_LENGTH_OUTPUT(_in_) \
	struct ZlangObject	*in1 = GetInputParameterInLocalObjectStack(rt,1) ; \
	struct ZlangObject	*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	double			d ; \
	int			data_len ; \
	\
	data_len = fscanf( _in_ , "%lf" , & d ) ; \
	CallRuntimeFunction_double_SetDoubleValue( rt , in1 , d ); \
	CallRuntimeFunction_int_SetIntValue( rt , out1 , data_len ); \

#define FGETS_STRING_AND_SET_LENGTH_OUTPUT(_in_) \
	struct ZlangObject	*in1 = GetInputParameterInLocalObjectStack(rt,1) ; \
	struct ZlangObject	*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	int32_t			data_len ; \
	\
	memset( _g_zlang_string_buffer , 0x00 , sizeof(_g_zlang_string_buffer) ); \
	if( fgets( _g_zlang_string_buffer , sizeof(_g_zlang_string_buffer)-1 , _in_ ) ) \
	{ \
		data_len = (int32_t)strlen(_g_zlang_string_buffer) ; \
		\
		if( data_len > 0 && _g_zlang_string_buffer[data_len-1] == '\n' ) \
		{ \
			_g_zlang_string_buffer[data_len-1] = '\0' ; \
			data_len--; \
			\
			if( data_len > 0 && _g_zlang_string_buffer[data_len-1] == '\r' ) \
			{ \
				_g_zlang_string_buffer[data_len-1] = '\0' ; \
				data_len--; \
			} \
		} \
		\
		data_len = FromCharPtr( rt , in1 , _g_zlang_string_buffer , data_len ) ; \
	} \
	else \
	{ \
		data_len = -1 ; \
	} \
	\
	CallRuntimeFunction_int_SetIntValue( rt , out1 , data_len ); \

#endif

